package kyssion.leetcode.num51_100;

public class code79_单词搜索 {
    public static void main(String[] args) {
        System.out.println(new code79_单词搜索().exist(
                new char[][]{
                        {'a','b'}
                },"ba"
        ));
    }

    public boolean exist(char[][] board, String word) {
        char[] chars = word.toCharArray();
        int[][] speeds = new int[board.length][board[0].length];
        for (int a = 0; a < board.length; a++) {
            for (int b = 0; b < board[a].length; b++) {
                speeds[a][b] = 1;
                if (board[a][b] == chars[0] && find(board, a, b, chars, 0, speeds)) {
                    return true;
                }
                speeds[a][b] = 0;
            }
        }
        return false;
    }

    public boolean find(char[][] board, int row, int col, char[] chars, int index, int[][] speeds) {
        if (index == chars.length - 1) {
            return true;
        }
        if (board[row][col] == chars[index]) {
            boolean isOk;
            if (row - 1 >= 0 && speeds[row - 1][col] == 0 && board[row - 1][col] == chars[index + 1]) {
                speeds[row][col] = 1;
                isOk = find(board, row - 1, col, chars, index + 1, speeds);
                if (isOk) {
                    return true;
                }
                speeds[row][col] = 0;
            }

            if (col - 1 >= 0 && speeds[row][col - 1] == 0 && board[row][col - 1] == chars[index + 1]) {
                speeds[row][col] = 1;
                isOk = find(board, row, col - 1, chars, index + 1, speeds);
                if (isOk) {
                    return true;
                }
                speeds[row][col] = 0;
            }

            if (row + 1 < board.length && speeds[row + 1][col] == 0 && board[row + 1][col] == chars[index + 1]) {
                speeds[row][col] = 1;
                isOk = find(board, row + 1, col, chars, index + 1, speeds);
                if (isOk) {
                    return true;
                }
                speeds[row][col] = 0;
            }

            if (col + 1 < board[0].length && speeds[row][col + 1] == 0 && board[row][col + 1] == chars[index + 1]) {
                speeds[row][col] = 1;
                isOk = find(board, row, col + 1, chars, index + 1, speeds);
                if (isOk) {
                    return true;
                }
                speeds[row][col] = 0;
            }
        }
        return false;
    }

    /**
     * 其实写这个代码有一个技巧就是将特殊的关键点列出来,能更加方便的事先代码逻辑
     * @param board
     * @param word
     * @return
     */
    public boolean exist2(char[][] board, String word) {
        boolean[][] visited = new boolean[board.length][board[0].length];
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[0].length; j++) {
                if (dfs(board, word, 0, i, j, visited)) {
                    return true;
                }

            }
        }
        return false;
    }

    private boolean dfs(char[][] board, String word, int index, int x, int y, boolean[][] visited) {
        //终止条件
        if (index == word.length()) {
            return true;
        }
        //越界
        if (x < 0 || y < 0 || x >= board.length || y >= board[0].length) {
            return false;
        }
        //已经访问
        if (visited[x][y]) {
            return false;
        }
        //不相等
        if (board[x][y] != word.charAt(index)) {
            return false;
        }
        visited[x][y] = true;
        boolean result = dfs(board, word, index + 1, x - 1, y, visited) || dfs(board, word, index + 1, x + 1, y, visited) || dfs(board, word, index + 1, x, y - 1, visited) || dfs(board, word, index + 1, x, y + 1, visited);//分别为上下左右地搜索.
        visited[x][y] = false; //准备回溯,设置回未访问状态.
        return result;
    }
}
